/***********************************************
*Copyright(c)2022,成都东软学院 操作系统课程组
*Allrightsreserved.
*文件名称：deadlock.c
*文件标识：
*摘  要：线程互斥,引发的死锁
*
*当前版本：1.1
*作  者：贾志东
*完成日期：2024年4月22日
*************************************************/

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
// 线程1从账号1向账号2转账
// 线程2从账号2向账号1转账
int accountNum1 = 5000; //账号1,公共变量（互斥资源）
int accountNum2 = 3000; //账号2,公共变量（互斥资源）
//初始化静态分配的互斥锁（互斥量）
//对于静态初始化的互斥锁（互斥量），不需要调用 pthread_mutex_init() 函数
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;

void * pthread_fuction_1();//线程1
void * pthread_fuction_2();//线程2
//时间延迟
void  delay_s(int s);

int main(int argc, char *argv[])
{
    int retn;           //线程创建函数返回值
    pthread_t tid1;     //线程1的ID
    pthread_t tid2;     //线程2的ID
    pthread_mutex_init(&lock1, NULL);//初始化互斥锁
    pthread_mutex_init(&lock2, NULL);//初始化互斥锁
    //创建线程1
    retn = pthread_create(&tid1,NULL,pthread_fuction_1,NULL);
    if (retn != 0)
        printf("线程1创建失败!");
    //创建线程2
    retn = pthread_create(&tid2,NULL,pthread_fuction_2,NULL);
    if (retn != 0)
        printf("线程2创建失败!");
    //等待线程1结束
    retn = pthread_join(tid1,NULL);
    if (retn != 0)
        printf("pthread_join error");
        //等待线程2结束
    retn = pthread_join(tid2,NULL);
    if (retn != 0)
        printf("pthread_join error");
    //销毁互斥锁
    pthread_mutex_destroy(&lock1);
    pthread_mutex_destroy(&lock2);
    exit(0);
}

void * pthread_fuction_1()
{
    // 转账次数
    int payment = 5;
    delay_s(2);
    while(payment>=0)
    {
        //账号1上锁
        pthread_mutex_lock(&lock1);
        printf("线程1( %u) 申请账号1成功\n",pthread_self());
        pthread_mutex_lock(&lock2);
        printf("线程1( %u) 申请账号2成功\n",pthread_self());
        // 模拟1秒事务处理 在事务处理前必须保证两个账号都申请成功
        delay_s(1);
        payment--;      
        printf("线程1( %u) 第 %d 次转账5万元 \n",pthread_self(),5-payment);
        accountNum1=accountNum1-5;
        accountNum2=accountNum2+5;
        // 模拟1秒钟的事务处理
        delay_s(1);
        //解锁
        pthread_mutex_unlock(&lock2);   
        pthread_mutex_unlock(&lock1);
        // 模拟1秒钟的事务处理
        delay_s(1); 
    }
     pthread_exit("a");
}

void * pthread_fuction_2()
{
    // 转账次数
    int payment = 5;
    while(payment>=0)
    {
        //账号2上锁
        pthread_mutex_lock(&lock2);
        printf("线程2( %u) 申请账号2成功\n",pthread_self());
        //账号1上锁
        pthread_mutex_lock(&lock1);
        printf("线程2( %u) 申请账号1成功\n",pthread_self());
        // 模拟1秒事务处理 同理
        delay_s(1);
        payment--;      
        printf("线程2( %u) 第 %d 次转账5万元 \n",pthread_self(),5-payment);
        accountNum2=accountNum2-5;
        accountNum1=accountNum1+5;
        // 模拟1秒钟的事务处理
        delay_s(1); 
        //解锁
        pthread_mutex_unlock(&lock1);   
        pthread_mutex_unlock(&lock2);
        // 模拟1秒钟的事务处理
        delay_s(1); 
    }
       pthread_exit("b");
}
//时间延迟函数,s:延迟秒数
void  delay_s(int s)
{
    time_t secStart,secEnd;
    int sec=0; 
    secStart = time((time_t *)NULL);
    while(sec<=s) {
        secEnd= time((time_t *)NULL);
        sec=secEnd-secStart;
    }
}
